From 8ff2288a9abae74f5e102f010ee34f9d4d13695e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Mar 2007 11:38:26 +0000 Subject: [PATCH] hvm: Add a revision 1 FADT in ACPI, and link the original revision-4 FADT only to XSDT. It avoids a buffer overflow in the initialization of Window 2000 ACPI HAL (pre ACPI 2.0 OS), and thus enables the installation and boot. This compatibility practice is also used in hardware, please refer to: http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt Signed-off-by: Qing He --- tools/firmware/hvmloader/acpi/acpi2_0.h | 46 +++++++++++++++++++++++++ tools/firmware/hvmloader/acpi/build.c | 22 +++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/tools/firmware/hvmloader/acpi/acpi2_0.h b/tools/firmware/hvmloader/acpi/acpi2_0.h index 7dde528a48..3e8424e138 100644 --- a/tools/firmware/hvmloader/acpi/acpi2_0.h +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h @@ -142,6 +142,51 @@ struct acpi_20_tcpa { }; #define ACPI_2_0_TCPA_LAML_SIZE (64*1024) +/* + * Fixed ACPI Description Table Structure (FADT) in ACPI 1.0. + */ +struct acpi_10_fadt { + struct acpi_header header; + uint32_t firmware_ctrl; + uint32_t dsdt; + uint8_t reserved0; + uint8_t preferred_pm_profile; + uint16_t sci_int; + uint32_t smi_cmd; + uint8_t acpi_enable; + uint8_t acpi_disable; + uint8_t s4bios_req; + uint8_t pstate_cnt; + uint32_t pm1a_evt_blk; + uint32_t pm1b_evt_blk; + uint32_t pm1a_cnt_blk; + uint32_t pm1b_cnt_blk; + uint32_t pm2_cnt_blk; + uint32_t pm_tmr_blk; + uint32_t gpe0_blk; + uint32_t gpe1_blk; + uint8_t pm1_evt_len; + uint8_t pm1_cnt_len; + uint8_t pm2_cnt_len; + uint8_t pm_tmr_len; + uint8_t gpe0_blk_len; + uint8_t gpe1_blk_len; + uint8_t gpe1_base; + uint8_t cst_cnt; + uint16_t p_lvl2_lat; + uint16_t p_lvl3_lat; + uint16_t flush_size; + uint16_t flush_stride; + uint8_t duty_offset; + uint8_t duty_width; + uint8_t day_alrm; + uint8_t mon_alrm; + uint8_t century; + uint16_t iapc_boot_arch; + uint8_t reserved1; + uint32_t flags; +}; + /* * Fixed ACPI Description Table Structure (FADT). */ @@ -345,6 +390,7 @@ struct acpi_20_madt_intsrcovr { #define ACPI_2_0_XSDT_REVISION 0x01 #define ACPI_2_0_TCPA_REVISION 0x02 #define ACPI_2_0_HPET_REVISION 0x01 +#define ACPI_1_0_FADT_REVISION 0x01 #pragma pack () diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c index 55a48d440e..3db71cabfe 100644 --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -293,6 +293,7 @@ int acpi_build_tables(uint8_t *buf) struct acpi_20_rsdt *rsdt; struct acpi_20_xsdt *xsdt; struct acpi_20_fadt *fadt; + struct acpi_10_fadt *fadt_10; struct acpi_20_facs *facs; unsigned char *dsdt; unsigned long secondary_tables[16]; @@ -306,6 +307,25 @@ int acpi_build_tables(uint8_t *buf) memcpy(dsdt, &AmlCode, DsdtLen); offset += align16(DsdtLen); + /* + * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2 + * or above properly, notably Windows 2000, which tries to copy FADT + * into a 116 bytes buffer thus causing an overflow. The solution is to + * link the higher revision FADT with the XSDT only and introduce a + * compatible revision 1 FADT that is linked with the RSDT. Refer to: + * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt + */ + fadt_10 = (struct acpi_10_fadt *)&buf[offset]; + memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt)); + offset += align16(sizeof(struct acpi_10_fadt)); + fadt_10->header.length = sizeof(struct acpi_10_fadt); + fadt_10->header.revision = ACPI_1_0_FADT_REVISION; + fadt_10->dsdt = (unsigned long)dsdt; + fadt_10->firmware_ctrl = (unsigned long)facs; + set_checksum(fadt_10, + offsetof(struct acpi_header, checksum), + sizeof(struct acpi_10_fadt)); + fadt = (struct acpi_20_fadt *)&buf[offset]; memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt)); offset += align16(sizeof(struct acpi_20_fadt)); @@ -332,7 +352,7 @@ int acpi_build_tables(uint8_t *buf) rsdt = (struct acpi_20_rsdt *)&buf[offset]; memcpy(rsdt, &Rsdt, sizeof(struct acpi_header)); - rsdt->entry[0] = (unsigned long)fadt; + rsdt->entry[0] = (unsigned long)fadt_10; for ( i = 0; secondary_tables[i]; i++ ) rsdt->entry[i+1] = secondary_tables[i]; rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t); -- 2.30.2